/**
 * 场景树形结构管理器
 * 用于管理场景中的所有对象节点（3D模型、空节点等）
 * 支持父子关系、节点移动、层级管理
 */

import * as THREE from 'three';
import { getMaterialLibraryManager } from '../model-library/MaterialLibraryManager.js';
import { addNodeMaterialReferences } from '../utils/materialReferenceHelper.js';

/**
 * 树节点类
 * 表示场景中的一个对象（可以是3D模型或空节点）
 */
export class TreeNode {
    constructor(options = {}) {
        // ✅ 统一ID系统：TreeNode 的 id 就是 object3D 的 uuid
        // 特殊情况：
        // 1. 根节点（type === 'root'）使用固定的 'root' ID
        // 2. 其他节点：如果有 object3D，使用其 uuid
        // 3. 从 JSON 加载时，使用保存的 id（后续会设置给 object3D.uuid）
        // 4. 否则生成新的 UUID
        if (options.type === 'root') {
            // 根节点固定 ID
            this.id = 'root';
        } else if (options.object3D && !options.id) {
            // 新创建的节点，使用 object3D 的 uuid
            this.id = options.object3D.uuid;
        } else if (options.id) {
            // 从 JSON 加载或显式传入 ID
            this.id = options.id;
        } else {
            // 空节点，生成新的 UUID
            this.id = THREE.MathUtils.generateUUID();
        }
        
        this.name = options.name || 'Untitled';
        this.type = options.type || 'empty'; // 'empty', 'model', 'group', 'mesh'
        this.object3D = options.object3D || null; // Three.js Object3D 引用
        this.userData = options.userData || {}; // 自定义数据
        
        // ✅ 组件系统（按需添加的组件）- 必须在使用 this.modelId 之前初始化
        this.components = options.components || [];
        
        // ✅ 移除冗余字段：
        //    - uuid：id 就是 uuid
        //    - modelId：只存在于 components 中
        //    - modelPath：可以通过 modelId 从 API 获取
        //    - baseScale：是模型的固有属性，从模型文件获取，不需要存储
        //    - transform：现在作为组件存储在 components 中
        
        // 注意：baseScale 不存储在数据中，但在内存中需要用于 transform 计算
        // 运行时通过 getBaseScale() 方法获取
        
        // ✅ 保存模型的原始缩放值（仅用于显示，不影响transform.scale计算）
        // 这个值在模型加载时被设置，之后不会改变
        this.originalScale = options.originalScale || { x: 1, y: 1, z: 1 };
        
        // ✅ Transform 作为组件存储
        // 检查是否已有 transform 组件
        let transformComponent = this.components.find(c => c.type === 'transform');
        
        if (!transformComponent) {
            // 创建默认 transform 组件
            const defaultTransform = {
                position: { x: 0, y: 0, z: 0 },
                rotation: { x: 0, y: 0, z: 0 }, // 欧拉角（弧度）
                scale: { x: 1, y: 1, z: 1 } // 节点缩放从1开始
            };
            
            // 如果有传入的 transform（旧格式兼容），使用传入的值
            const transformData = options.transform || defaultTransform;
            
            // 如果有 object3D 且没有提供 transform，从 object3D 初始化
            if (this.object3D && !options.transform) {
                // 保存object3D的原始缩放（如FBX的0.01）
                if (!options.originalScale && this.modelId) {
                    this.originalScale = {
                        x: this.object3D.scale.x,
                        y: this.object3D.scale.y,
                        z: this.object3D.scale.z
                    };
                }
                
                transformData.position = {
                    x: this.object3D.position.x,
                    y: this.object3D.position.y,
                    z: this.object3D.position.z
                };
                transformData.rotation = {
                    x: this.object3D.rotation.x,
                    y: this.object3D.rotation.y,
                    z: this.object3D.rotation.z
                };
                transformData.scale = { x: 1, y: 1, z: 1 }; // transform.scale永远从1开始
            }
            
            // 添加 transform 组件
            transformComponent = {
                type: 'transform',
                ...transformData
            };
            this.components.push(transformComponent);
        } else if (this.object3D && !options.transform) {
            // 如果已有组件但有 object3D 且没提供 transform，从 object3D 更新
            if (!options.originalScale && this.modelId) {
                this.originalScale = {
                    x: this.object3D.scale.x,
                    y: this.object3D.scale.y,
                    z: this.object3D.scale.z
                };
            }
        }
        
        // 树结构
        this.parent = null;
        this.children = [];
        
        // 可见性和激活状态
        this.visible = options.visible !== undefined ? options.visible : true;
        this.locked = options.locked || false; // 是否锁定（不可编辑）
        
        // 创建时间
        this.createdAt = new Date();
    }
    
    /**
     * 获取节点关联的模型ID
     * @returns {string|null} 模型ID，如果节点没有关联模型则返回 null
     */
    get modelId() {
        const modelComponent = this.components.find(c => c.type === 'model');
        return modelComponent ? modelComponent.modelId : null;
    }
    
    /**
     * 获取节点关联的模型类型
     * @returns {string} 模型类型（'model' 或 'node'），默认 'model'
     */
    get modelType() {
        const modelComponent = this.components.find(c => c.type === 'model');
        return modelComponent ? (modelComponent.modelType || 'model') : 'model';
    }
    
    /**
     * 获取 transform 数据（从 components 中获取）
     * @returns {Object} transform 数据 {position, rotation, scale}
     */
    get transform() {
        const transformComponent = this.components.find(c => c.type === 'transform');
        if (transformComponent) {
            return {
                position: transformComponent.position || { x: 0, y: 0, z: 0 },
                rotation: transformComponent.rotation || { x: 0, y: 0, z: 0 },
                scale: transformComponent.scale || { x: 1, y: 1, z: 1 },
                isLocalCoordinates: transformComponent.isLocalCoordinates // 🔑 保留 isLocalCoordinates 标记
            };
        }
        // 默认值
        return {
            position: { x: 0, y: 0, z: 0 },
            rotation: { x: 0, y: 0, z: 0 },
            scale: { x: 1, y: 1, z: 1 }
        };
    }
    
    /**
     * 设置 transform 数据（更新 components 中的 transform 组件）
     * @param {Object} value - transform 数据 {position, rotation, scale}
     */
    set transform(value) {
        let transformComponent = this.components.find(c => c.type === 'transform');
        
        if (!transformComponent) {
            // 如果没有 transform 组件，创建一个
            transformComponent = {
                type: 'transform',
                position: { x: 0, y: 0, z: 0 },
                rotation: { x: 0, y: 0, z: 0 },
                scale: { x: 1, y: 1, z: 1 }
            };
            this.components.push(transformComponent);
        }
        
        // 更新组件数据
        if (value.position) {
            transformComponent.position = { ...value.position };
        }
        if (value.rotation) {
            transformComponent.rotation = { ...value.rotation };
        }
        if (value.scale) {
            transformComponent.scale = { ...value.scale };
        }
    }
    
    /**
     * 获取模型的基础缩放值
     * @returns {number} 基础缩放值（FBX=0.01, GLTF/GLB=1, 空节点=1）
     */
    getBaseScale() {
        // 如果节点有模型组件，根据模型类型确定 baseScale
        const modelComponent = this.components.find(c => c.type === 'model');
        if (modelComponent && modelComponent.modelId) {
            // ✅ 优先从 object3D.userData 读取文件类型（modelLoader 加载时设置）
            if (this.object3D && this.object3D.userData && this.object3D.userData.fileType) {
                const fileType = this.object3D.userData.fileType;
                if (fileType === 'fbx') {
                    return 0.01;
                } else if (fileType === 'gltf' || fileType === 'glb') {
                    return 1.0;
                }
            }
            
            // ✅ 其次使用模型组件中存储的 fileType（向后兼容）
            if (modelComponent.fileType) {
                if (modelComponent.fileType === 'fbx') {
                    return 0.01;
                } else if (modelComponent.fileType === 'gltf' || modelComponent.fileType === 'glb') {
                    return 1.0;
                }
            }
            
            // ✅ 最后通过世界缩放推断（兜底方案）
            // 使用世界缩放而不是本地缩放，避免被父节点缩放影响
            if (this.object3D) {
                const worldScale = new THREE.Vector3();
                this.object3D.getWorldScale(worldScale);
                
                // 如果世界缩放接近 0.01（允许用户调整倍数，比如0.005-0.05范围）
                // 说明是 FBX 模型（baseScale=0.01）
                const avgWorldScale = (worldScale.x + worldScale.y + worldScale.z) / 3;
                if (avgWorldScale < 0.1 && avgWorldScale > 0.001) {
                    return 0.01;
                }
            }
            
            // 默认假设是 FBX（因为当前项目主要使用 FBX）
            return 0.01;
        }
        
        // 空节点或其他类型，baseScale 为 1
        return 1;
    }
    
    /**
     * 保存模型内部所有层级的原始transform
     * 这会遍历object3D的整个层次结构，保存每个子对象的原始transform
     */
    saveModelHierarchyTransforms() {
        if (!this.object3D) {
            console.warn('⚠️ [保存模型层级Transform] 节点没有object3D');
            return;
        }
        
        // 初始化保存Map（如果还没有）
        if (!this._modelHierarchyTransforms) {
            this._modelHierarchyTransforms = new Map();
        }
        
        // 遍历object3D的所有子对象（包括Group、Mesh等）
        this.object3D.traverse((child) => {
            // 保存每个对象的transform
            this._modelHierarchyTransforms.set(child.uuid, {
                position: child.position.clone(),
                rotation: child.rotation.clone(),
                scale: child.scale.clone(),
                name: child.name || '(unnamed)',
                type: child.type
            });
        });
    }
    
    /**
     * 重置模型内部所有层级的transform到原始状态
     * 这会恢复object3D层次结构中每个子对象的原始transform
     */
    resetModelHierarchyTransforms() {
        if (!this.object3D) {
            console.warn('⚠️ [重置模型层级Transform] 节点没有object3D');
            return;
        }
        
        if (!this._modelHierarchyTransforms || this._modelHierarchyTransforms.size === 0) {
            console.warn('⚠️ [重置模型层级Transform] 没有保存的原始transform数据');
            return;
        }
        
        let restoredCount = 0;
        let notFoundCount = 0;
        
        // 遍历object3D的所有子对象
        this.object3D.traverse((child) => {
            // 检查是否有保存的transform
            if (this._modelHierarchyTransforms.has(child.uuid)) {
                const originalTransform = this._modelHierarchyTransforms.get(child.uuid);
                
                // 恢复transform
                child.position.copy(originalTransform.position);
                child.rotation.copy(originalTransform.rotation);
                child.scale.copy(originalTransform.scale);
                
                // 更新矩阵
                child.updateMatrix();
                child.updateMatrixWorld(true);
                
                restoredCount++;
            } else {
                notFoundCount++;
            }
        });
        
        // 强制渲染更新
        const currentScene = window.manager?.getCurrentScene();
        if (currentScene && currentScene.renderer) {
            currentScene.renderer.render(currentScene.scene, currentScene.camera);
        }
        
        return {
            restored: restoredCount,
            notFound: notFoundCount
        };
    }
    
    /**
     * 检查是否已保存模型层级transform
     */
    hasModelHierarchyTransforms() {
        return this._modelHierarchyTransforms && this._modelHierarchyTransforms.size > 0;
    }
    
    /**
     * 添加子节点
     */
    addChild(child) {
        if (!(child instanceof TreeNode)) {
            console.error('❌ 子节点必须是 TreeNode 实例');
            return false;
        }
        
        // ⚠️ 重要：在更新 TreeNode 父子关系之前判断是否是移动操作
        // 如果节点已经有父节点（TreeNode 的 parent），说明是移动操作，需要使用 attach()
        // 如果没有父节点，说明是新创建的节点，需要使用 add()
        const isMovingNode = child.parent !== null;
        const oldParent = child.parent;
        
        // 如果是移动操作，在更新前保存世界坐标和父节点信息
        let worldPositionBeforeMove = null;
        let localPositionBeforeMove = null;
        let oldParentNameBeforeMove = null;
        
        if (isMovingNode && child.object3D) {
            worldPositionBeforeMove = new THREE.Vector3();
            child.object3D.getWorldPosition(worldPositionBeforeMove);
            localPositionBeforeMove = child.object3D.position.clone();
            oldParentNameBeforeMove = child.object3D.parent?.name || 'Scene';
        }
        
        // 更新 TreeNode 的父子关系（不要调用 removeChild，避免影响 object3D.parent）
        if (oldParent) {
            const index = oldParent.children.indexOf(child);
            if (index !== -1) {
                oldParent.children.splice(index, 1);
            }
        }
        
        child.parent = this;
        this.children.push(child);
        
        // 更新 Three.js 的父子关系
        if (child.object3D) {
            const targetParent = this.object3D ? this.object3D : this.findAncestorWithObject3D()?.object3D;
            
            if (targetParent) {
                // 关键修复：不再手动调用 removeChild()，让 attach() 自己处理重新父化
                // 这样 child.object3D.parent 在 attach() 调用时仍然指向旧父节点
                // attach() 能正确获取世界坐标并保持不变
                
                if (!isMovingNode) {
                    // 新创建的节点：使用 add() 方法，保持本地坐标
                    // 这样新节点的本地坐标 (0, 0, 0) 会相对于父节点
                    
                    // 🎯 检查是否为节点组子节点（从父节点模型层级中获取的）
                    const modelComponent = child.components.find(c => c.type === 'model');
                    const isHierarchyChild = modelComponent && modelComponent.fromHierarchy;
                    
                    // 避免重复添加
                    if (child.object3D.parent !== targetParent) {
                        targetParent.add(child.object3D);
                        
                        // ✅ 节点组子节点：object3D 已经在父节点的层级中，有正确的相对transform
                        // ❌ 不要应用 transform！因为 object3D 的 transform 已经是正确的
                        if (!isHierarchyChild) {
                            // 只对非节点组子节点应用 transform
                            child.applyTransformToObject3D();
                        }
                    } else if (isHierarchyChild) {
                        // 🎯 节点组子节点：object3D已经是父对象的子对象
                        // ✅ 修复：不要应用 transform！object3D 已经有正确的相对transform
                    }
                } else {
                    // 移动已存在的节点：使用 attach() 方法，保持世界坐标
                    // 执行 attach - 这会自动保持世界坐标不变
                    targetParent.attach(child.object3D);
                    
                    // ✅ 更新 transform 数据为新的世界坐标
                    // 注意：transform 保存的是世界坐标，attach() 保持世界坐标不变，所以只需读取即可
                    const worldPos = new THREE.Vector3();
                    const worldQuat = new THREE.Quaternion();
                    const worldScale = new THREE.Vector3();
                    
                    child.object3D.getWorldPosition(worldPos);
                    child.object3D.getWorldQuaternion(worldQuat);
                    child.object3D.getWorldScale(worldScale);
                    
                    const worldEuler = new THREE.Euler().setFromQuaternion(worldQuat);
                    
                    // 更新世界坐标到 transform
                    child.transform.position.x = parseFloat(worldPos.x.toFixed(3));
                    child.transform.position.y = parseFloat(worldPos.y.toFixed(3));
                    child.transform.position.z = parseFloat(worldPos.z.toFixed(3));
                    
                    child.transform.rotation.x = parseFloat(worldEuler.x.toFixed(4));
                    child.transform.rotation.y = parseFloat(worldEuler.y.toFixed(4));
                    child.transform.rotation.z = parseFloat(worldEuler.z.toFixed(4));
                    
                    // ✅ 缩放：保存世界用户缩放（物理缩放 ÷ importScale）
                    // attach() 保持世界物理缩放不变，需要除以 importScale 得到用户缩放
                    const importScale = child.object3D.userData?.importScale || 1.0;
                    child.transform.scale.x = parseFloat((worldScale.x / importScale).toFixed(3));
                    child.transform.scale.y = parseFloat((worldScale.y / importScale).toFixed(3));
                    child.transform.scale.z = parseFloat((worldScale.z / importScale).toFixed(3));
                }
            }
        }
        
        return true;
    }
    
    /**
     * 移除子节点
     * 注意：这个方法只在真正删除节点时调用，移动节点时不应该调用
     */
    removeChild(child) {
        const index = this.children.indexOf(child);
        if (index === -1) {
            console.warn('⚠️ 子节点不存在');
            return false;
        }
        
        this.children.splice(index, 1);
        child.parent = null;
        
        // 同时从 Three.js 场景中移除
        if (this.object3D && child.object3D) {
            this.object3D.remove(child.object3D);
        }
        
        return true;
    }
    
    /**
     * 移动到新的父节点
     */
    moveTo(newParent) {
        if (!(newParent instanceof TreeNode)) {
            console.error('❌ 新父节点必须是 TreeNode 实例');
            return false;
        }
        
        // 不能移动到自己的子节点
        if (this.isAncestorOf(newParent)) {
            console.error('❌ 不能移动到自己的子节点');
            return false;
        }
        
        return newParent.addChild(this);
    }
    
    /**
     * 检查是否是指定节点的祖先
     */
    isAncestorOf(node) {
        let current = node.parent;
        while (current) {
            if (current === this) return true;
            current = current.parent;
        }
        return false;
    }
    
    /**
     * 获取所有祖先节点（从父节点到根节点）
     */
    getAncestors() {
        const ancestors = [];
        let current = this.parent;
        while (current) {
            ancestors.push(current);
            current = current.parent;
        }
        return ancestors;
    }
    
    /**
     * 查找最近的具有 object3D 的祖先节点
     */
    findAncestorWithObject3D() {
        let current = this.parent;
        while (current) {
            if (current.object3D) {
                return current;
            }
            current = current.parent;
        }
        return null;
    }
    
    /**
     * 获取节点深度（距离根节点的层级）
     */
    getDepth() {
        let depth = 0;
        let current = this.parent;
        while (current) {
            depth++;
            current = current.parent;
        }
        return depth;
    }
    
    /**
     * 获取节点路径（从根到当前节点的完整路径）
     */
    getPath() {
        const path = [this.name];
        let current = this.parent;
        while (current) {
            path.unshift(current.name);
            current = current.parent;
        }
        return path.join(' / ');
    }
    
    /**
     * 遍历所有子节点（深度优先）
     */
    traverse(callback) {
        callback(this);
        this.children.forEach(child => child.traverse(callback));
    }
    
    /**
     * 设置可见性
     */
    setVisible(visible) {
        this.visible = visible;
        if (this.object3D) {
            this.object3D.visible = visible;
        }
        // 递归设置所有子节点
        this.children.forEach(child => child.setVisible(visible));
    }
    
    /**
     * 切换可见性
     */
    toggleVisible() {
        this.setVisible(!this.visible);
    }
    
    /**
     * 导出为JSON
     * ✅ 保存世界矩阵数据（绝对坐标），而不是本地坐标
     * ✅ transform 数据保存在 components 中
     */
    toJSON() {
        // ✅ 深拷贝 components 以避免修改原始数据
        const componentsToSave = JSON.parse(JSON.stringify(this.components || []));
        
        // ✅ 如果有 object3D，更新 transform 组件为世界坐标
        if (this.object3D) {
            const worldPosition = new THREE.Vector3();
            const worldQuaternion = new THREE.Quaternion();
            const worldScale = new THREE.Vector3();
            
            // 获取世界矩阵分解后的值
            this.object3D.getWorldPosition(worldPosition);
            this.object3D.getWorldQuaternion(worldQuaternion);
            this.object3D.getWorldScale(worldScale);
            
            // 将四元数转换为欧拉角
            const worldEuler = new THREE.Euler().setFromQuaternion(worldQuaternion);
            
            // 查找或创建 transform 组件
            let transformComponent = componentsToSave.find(c => c.type === 'transform');
            if (!transformComponent) {
                transformComponent = { type: 'transform' };
                componentsToSave.push(transformComponent);
            }
            
            // 更新为世界坐标
            transformComponent.position = {
                x: worldPosition.x,
                y: worldPosition.y,
                z: worldPosition.z
            };
            transformComponent.rotation = {
                x: worldEuler.x,
                y: worldEuler.y,
                z: worldEuler.z
            };
            
            // ✅ 保存"用户缩放"（物理缩放 ÷ importScale）
            // worldScale 是物理缩放，需要除以 importScale 得到用户看到的逻辑值
            const importScale = this.object3D.userData?.importScale || 1.0;
            transformComponent.scale = {
                x: worldScale.x / importScale,
                y: worldScale.y / importScale,
                z: worldScale.z / importScale
            };
        }
        
        // ✅ 保存 importScale 到输出数据（如果存在）
        const importScale = this.object3D?.userData?.importScale;
        
        return {
            id: this.id, // ✅ id 就是 Three.js Object3D 的 uuid
            name: this.name,
            type: this.type,
            visible: this.visible,
            locked: this.locked,
            userData: this.userData,
            // ✅ 保存导入缩放系数（仅在有值且不为1时保存，减少数据冗余）
            ...(importScale && importScale !== 1.0 ? { importScale } : {}),
            // ✅ transform 数据现在在 components 中
            components: componentsToSave, // ✅ 包含 transform、model 等所有组件
            // ✅ 保存所有子节点（包括环境节点）
            children: this.children.map(child => child.toJSON())
        };
    }
    
    /**
     * 获取本地坐标（相对父节点）
     * ✅ 用于 Transform 面板显示，从世界坐标计算得出
     */
    getLocalTransform() {
        if (!this.object3D) {
            // 如果没有 object3D，返回默认值
            return {
                position: { x: 0, y: 0, z: 0 },
                rotation: { x: 0, y: 0, z: 0 },
                scale: { x: 1, y: 1, z: 1 }
            };
        }
        
        // 直接返回 object3D 的本地坐标
        return {
            position: {
                x: this.object3D.position.x,
                y: this.object3D.position.y,
                z: this.object3D.position.z
            },
            rotation: {
                x: this.object3D.rotation.x,
                y: this.object3D.rotation.y,
                z: this.object3D.rotation.z
            },
            scale: {
                x: this.object3D.scale.x,
                y: this.object3D.scale.y,
                z: this.object3D.scale.z
            }
        };
    }
    
    /**
     * 更新Transform并应用到Three.js对象
     * ✅ 接收本地坐标（Transform面板的输入），转换为世界坐标后保存
     */
    updateTransform(localTransform) {
        if (!this.object3D) return;
        
        // 1. 先应用本地坐标到 object3D
        if (localTransform.position) {
            this.object3D.position.set(
                localTransform.position.x,
                localTransform.position.y,
                localTransform.position.z
            );
        }
        if (localTransform.rotation) {
            this.object3D.rotation.set(
                localTransform.rotation.x,
                localTransform.rotation.y,
                localTransform.rotation.z
            );
        }
        if (localTransform.scale) {
            this.object3D.scale.set(
                localTransform.scale.x,
                localTransform.scale.y,
                localTransform.scale.z
            );
        }
        
        // 2. 更新世界矩阵
        this.object3D.updateMatrixWorld(true);
        
        // 3. 从 object3D 获取世界坐标并保存到 this.transform
        const worldPosition = new THREE.Vector3();
        const worldQuaternion = new THREE.Quaternion();
        const worldScale = new THREE.Vector3();
        
        this.object3D.getWorldPosition(worldPosition);
        this.object3D.getWorldQuaternion(worldQuaternion);
        this.object3D.getWorldScale(worldScale);
        
        const worldEuler = new THREE.Euler().setFromQuaternion(worldQuaternion);
        
        // ✅ 保存世界坐标
        this.transform = {
            position: {
                x: worldPosition.x,
                y: worldPosition.y,
                z: worldPosition.z
            },
            rotation: {
                x: worldEuler.x,
                y: worldEuler.y,
                z: worldEuler.z
            },
            scale: {
                x: worldScale.x,
                y: worldScale.y,
                z: worldScale.z
            }
        };
    }
    
    /**
     * 将transform数据（世界坐标）应用到Three.js对象
     * ✅ transform 保存的是世界坐标，需要转换为本地坐标后应用
     */
    applyTransformToObject3D() {
        if (!this.object3D) return;
        
        // ✅ transform 可能是世界坐标或本地坐标，根据 isLocalCoordinates 标记来判断
        
        // ✅ 获取 importScale（用于将用户缩放转换为物理缩放）
        const importScale = this.object3D.userData?.importScale || 1.0;
        
        // 🔑 如果是本地坐标，直接应用
        const isLocal = this.transform.isLocalCoordinates === true;
        if (isLocal) {
            // 本地坐标：直接应用 position, rotation, scale
            console.log(`🔧 [apply-local] ${this.name} | 应用前: (${this.object3D.scale.x.toFixed(3)}, ${this.object3D.scale.y.toFixed(3)}, ${this.object3D.scale.z.toFixed(3)}) | transform: (${this.transform.scale.x}, ${this.transform.scale.y}, ${this.transform.scale.z})`);
            
            this.object3D.position.set(
                this.transform.position.x,
                this.transform.position.y,
                this.transform.position.z
            );
            this.object3D.rotation.set(
                this.transform.rotation.x,
                this.transform.rotation.y,
                this.transform.rotation.z
            );
            // scale 是本地物理缩放，直接应用
            this.object3D.scale.set(
                this.transform.scale.x,
                this.transform.scale.y,
                this.transform.scale.z
            );
            return;
        }
        
        // 🌍 世界坐标：需要转换为本地坐标
        if (!this.object3D.parent) {
            // 没有父节点，世界坐标 = 本地坐标
            this.object3D.position.set(
                this.transform.position.x,
                this.transform.position.y,
                this.transform.position.z
            );
            this.object3D.rotation.set(
                this.transform.rotation.x,
                this.transform.rotation.y,
                this.transform.rotation.z
            );
            // ✅ transform.scale 是用户缩放，需要乘以 importScale 得到物理缩放
            this.object3D.scale.set(
                this.transform.scale.x * importScale,
                this.transform.scale.y * importScale,
                this.transform.scale.z * importScale
            );
        } else {
            // 有父节点，需要从世界坐标转换为本地坐标
            
            // 1. 创建世界矩阵
            const worldPosition = new THREE.Vector3(
                this.transform.position.x,
                this.transform.position.y,
                this.transform.position.z
            );
            const worldRotation = new THREE.Euler(
                this.transform.rotation.x,
                this.transform.rotation.y,
                this.transform.rotation.z
            );
            const worldQuaternion = new THREE.Quaternion().setFromEuler(worldRotation);
            // ✅ transform.scale 是用户缩放，需要乘以 importScale 得到物理缩放
            const worldScale = new THREE.Vector3(
                this.transform.scale.x * importScale,
                this.transform.scale.y * importScale,
                this.transform.scale.z * importScale
            );
            
            const worldMatrix = new THREE.Matrix4();
            worldMatrix.compose(worldPosition, worldQuaternion, worldScale);
            
            // 2. 获取父节点的世界矩阵的逆矩阵
            const parentWorldMatrix = new THREE.Matrix4();
            this.object3D.parent.updateMatrixWorld(true);
            parentWorldMatrix.copy(this.object3D.parent.matrixWorld);
            const parentWorldMatrixInverse = new THREE.Matrix4().copy(parentWorldMatrix).invert();
            
            // 3. 计算本地矩阵 = 父矩阵逆 × 世界矩阵
            const localMatrix = new THREE.Matrix4().multiplyMatrices(parentWorldMatrixInverse, worldMatrix);
            
            // 4. 从本地矩阵分解出本地变换
            const localPosition = new THREE.Vector3();
            const localQuaternion = new THREE.Quaternion();
            const localScale = new THREE.Vector3();
            localMatrix.decompose(localPosition, localQuaternion, localScale);
            
            // 5. 应用本地变换到 object3D
            this.object3D.position.copy(localPosition);
            this.object3D.quaternion.copy(localQuaternion);
            this.object3D.scale.copy(localScale);
        }
    }
    
    /**
     * 销毁节点（释放资源）
     */
    dispose() {
        // 先销毁所有子节点
        [...this.children].forEach(child => child.dispose());
        
        // 从父节点移除
        if (this.parent) {
            this.parent.removeChild(this);
        }
        
        // 从Three.js场景中移除对象
        if (this.object3D) {
            // 从父容器中移除（如果有父容器）
            if (this.object3D.parent) {
                this.object3D.parent.remove(this.object3D);
            }
            
            // 释放几何体和材质
            if (this.object3D.geometry) {
                this.object3D.geometry.dispose();
            }
            if (this.object3D.material) {
                if (Array.isArray(this.object3D.material)) {
                    this.object3D.material.forEach(m => m.dispose());
                } else {
                    this.object3D.material.dispose();
                }
            }
            
            // 递归清理所有子对象（Three.js对象可能有自己的子对象）
            if (this.object3D.children && this.object3D.children.length > 0) {
                [...this.object3D.children].forEach(child => {
                    this.object3D.remove(child);
                    if (child.geometry) child.geometry.dispose();
                    if (child.material) {
                        if (Array.isArray(child.material)) {
                            child.material.forEach(m => m.dispose());
                        } else {
                            child.material.dispose();
                        }
                    }
                });
            }
        }
        
        this.object3D = null;
        this.parent = null;
        this.children = [];
    }
}

/**
 * 场景树管理器
 * 管理整个场景的树形结构
 */
export class SceneTreeManager {
    constructor(scene) {
        this.scene = scene; // Three.js Scene 引用
        this.root = new TreeNode({
            id: 'root',
            name: 'Scene Root',
            type: 'root',
            object3D: scene
        });
        
        this.nodesMap = new Map(); // id -> TreeNode 快速查找
        this.nodesMap.set('root', this.root);
        
        this.selectedNode = null; // 当前选中的节点
        this.eventCallbacks = {}; // 事件回调
        
        // ✨ 创建固定的环境节点（不可删除、不可拖拽）
        // 创建一个 THREE.Group 作为环境节点的3D对象
        const envGroup = new THREE.Group();
        envGroup.name = '环境';
        envGroup.uuid = 'environment'; // 使用固定的 uuid
        
        this.environmentNode = new TreeNode({
            id: 'environment',
            name: '环境',
            type: 'environment',
            locked: true, // 锁定节点，防止编辑
            userData: { isEnvironment: true },
            object3D: envGroup,
            components: [
                {
                    type: 'transform',
                    position: { x: 0, y: 0, z: 0 },
                    rotation: { x: 0, y: 0, z: 0 },
                    scale: { x: 1, y: 1, z: 1 }
                }
            ]
        });
        this.root.children.unshift(this.environmentNode); // 插入到第一个位置
        this.environmentNode.parent = this.root;
        this.nodesMap.set('environment', this.environmentNode);
        
        // 将环境节点的 Group 添加到场景中
        if (this.scene) {
            this.scene.add(envGroup);
        }
    }
    
    /**
     * 添加节点到场景
     */
    addNode(options, parentId = 'root') {
        const parent = this.nodesMap.get(parentId);
        if (!parent) {
            console.error(`❌ 父节点不存在: ${parentId}`);
            return null;
        }
        
        const node = new TreeNode(options);
        parent.addChild(node);
        this.nodesMap.set(node.id, node);
        this.emit('nodeAdded', { node, parent });
        
        return node;
    }
    
    /**
     * 从3D对象创建节点
     */
    addNodeFromObject3D(object3D, name, parentId = 'root') {
        const type = this.getObject3DType(object3D);
        
        return this.addNode({
            name: name || object3D.name || `${type}-${Date.now()}`,
            type: type,
            object3D: object3D,
            userData: { ...object3D.userData }
        }, parentId);
    }
    
    /**
     * 判断 Object3D 的类型
     */
    getObject3DType(object3D) {
        if (object3D.isMesh) return 'mesh';
        if (object3D.isGroup) return 'group';
        if (object3D.isLight) return 'light';
        if (object3D.isCamera) return 'camera';
        return 'object';
    }
    
    /**
     * 移除节点
     */
    async removeNode(nodeId) {
        const node = this.nodesMap.get(nodeId);
        if (!node) {
            console.error(`❌ 节点不存在: ${nodeId}`);
            return false;
        }
        
        if (node === this.root) {
            console.error('❌ 不能删除根节点');
            return false;
        }
        
        // ✨ 不能删除环境节点
        if (node === this.environmentNode || nodeId === 'environment') {
            console.error('❌ 不能删除环境节点');
            return false;
        }
        
        // 🔄 移除材质引用（递归处理当前节点及所有子节点）
        const currentProject = window.projectManager?.getCurrentProject();
        const sceneId = window.manager?.getCurrentSceneName();
        
        // 清理材质引用
        if (currentProject && sceneId) {
            const { removeNodeMaterialReferences } = await import('../utils/materialReferenceHelper.js');
            
            console.log(`🗑️ [删除调试] 开始清理节点 "${node.name}" 的材质引用`);
            console.log(`   - 节点类型: ${node.type}`);
            console.log(`   - 是否有children: ${node.children?.length || 0} 个子节点`);
            
            // 收集需要清理的节点
            const nodesToClean = [];
            node.traverse(n => {
                const modelComp = n.components?.find(c => c.type === 'model');
                if (modelComp && modelComp.meshMaterials && Object.keys(modelComp.meshMaterials).length > 0) {
                    nodesToClean.push({ node: n, modelComponent: modelComp });
                }
            });
            
            // 移除材质引用
            if (nodesToClean.length > 0) {
                console.log(`🔄 [删除调试] 开始调用后端API移除引用...`);
                let totalSuccess = 0;
                let totalFailed = 0;
                
                for (const { node: n, modelComponent } of nodesToClean) {
                    console.log(`📤 [删除调试] 调用API删除节点 "${n.name}" 的材质引用`);
                    console.log(`   - projectId: ${currentProject.id}`);
                    console.log(`   - sceneId: ${sceneId}`);
                    console.log(`   - nodeId: ${n.id}`);
                    console.log(`   - meshMaterials:`, modelComponent.meshMaterials);
                    
                    try {
                        const result = await removeNodeMaterialReferences(
                            currentProject.id,
                            modelComponent.meshMaterials,
                            sceneId,
                            n.id
                        );
                        
                        console.log(`📥 [删除调试] API返回结果:`, result);
                        console.log(`   - 成功: ${result.success}`);
                        console.log(`   - 失败: ${result.failed}`);
                        
                        totalSuccess += result.success;
                        totalFailed += result.failed;
                    } catch (error) {
                        console.error(`❌ [删除调试] 移除材质引用失败:`, error);
                        console.error(`   错误堆栈:`, error.stack);
                    }
                }
                
                console.log(`✅ [删除调试] 所有节点处理完成`);
                console.log(`   - 总成功: ${totalSuccess}`);
                console.log(`   - 总失败: ${totalFailed}`);
                
                if (totalFailed > 0) {
                    console.warn(`⚠️ 材质引用移除: ${totalSuccess}成功, ${totalFailed}失败`);
                }
                
                // 刷新材质面板
                if (totalSuccess > 0) {
                    console.log(`🔄 [删除调试] 设置延迟刷新材质面板 (1000ms后)`);
                    setTimeout(() => {
                        console.log(`🔄 [删除调试] 现在开始刷新材质面板...`);
                        if (typeof window.forceRefreshMaterialDisplays === 'function') {
                            window.forceRefreshMaterialDisplays('节点删除');
                        } else {
                            console.error(`❌ [删除调试] window.forceRefreshMaterialDisplays 不存在！`);
                        }
                    }, 1000);
                } else {
                    console.log(`⚠️ [删除调试] 没有成功的删除，跳过刷新`);
                }
            } else {
                console.log(`ℹ️ [删除调试] 没有需要清理的节点`);
            }
        }
        
        // ⚠️ 重要：必须先检查mesh面板，再取消选中节点！
        // 因为 deselectNode() 会清空 _currentMeshEditNode，导致无法检测
        
        // 1. 先检查mesh结构面板是否显示了被删除节点的信息
        if (window.sceneTreeUI) {
            const meshPanel = document.getElementById('mesh-structure-panel');
            if (meshPanel && meshPanel.classList.contains('active')) {
                // 检查 _currentMeshEditNode 或 _previousNode
                const currentMeshNode = window.sceneTreeUI._currentMeshEditNode || window.sceneTreeUI._previousNode;
                
                if (currentMeshNode) {
                    // 检查被删除的节点是否是当前显示在mesh面板中的节点，或者是其祖先节点
                    let meshDisplayNode = currentMeshNode;
                    let shouldClearMeshPanel = false;
                    
                    // 向上遍历mesh显示节点的祖先链，检查是否包含被删除的节点
                    while (meshDisplayNode) {
                        if (meshDisplayNode.id === node.id) {
                            shouldClearMeshPanel = true;
                            break;
                        }
                        meshDisplayNode = meshDisplayNode.parent;
                    }
                    
                    if (shouldClearMeshPanel) {
                        window.sceneTreeUI.exitMeshEditMode();
                    }
                }
            }
        }
        
        // 2. 如果删除的是当前选中的节点或其子节点，取消选中
        if (this.selectedNode) {
            // 检查选中的节点是否是被删除的节点或其子节点
            let nodeToCheck = this.selectedNode;
            while (nodeToCheck) {
                if (nodeToCheck.id === node.id) {
                    this.deselectNode();
                    break;
                }
                nodeToCheck = nodeToCheck.parent;
            }
        }
        
        // 3. 递归删除所有子节点的映射
        node.traverse(n => {
            this.nodesMap.delete(n.id);
        });
        
        const parent = node.parent;
        node.dispose();
        this.emit('nodeRemoved', { node, parent });
        
        return true;
    }
    
    /**
     * 移动节点到新父节点
     */
    moveNode(nodeId, newParentId, index = -1) {
        const node = this.nodesMap.get(nodeId);
        const newParent = this.nodesMap.get(newParentId);
        
        if (!node || !newParent) {
            console.error('❌ 节点或父节点不存在');
            return false;
        }
        
        if (node === this.root) {
            console.error('❌ 不能移动根节点');
            return false;
        }
        
        // ✨ 不能移动环境节点
        if (node === this.environmentNode || nodeId === 'environment') {
            console.error('❌ 不能移动环境节点');
            return false;
        }
        
        const oldParent = node.parent;
        const success = node.moveTo(newParent);
        
        if (success) {
            // 如果指定了索引，调整顺序
            if (index >= 0 && index < newParent.children.length) {
                const currentIndex = newParent.children.indexOf(node);
                if (currentIndex !== -1) {
                    newParent.children.splice(currentIndex, 1);
                    newParent.children.splice(index, 0, node);
                }
            }
            this.emit('nodeMoved', { node, oldParent, newParent });
        }
        
        return success;
    }
    
    /**
     * 根据ID查找节点
     */
    findNodeById(id) {
        return this.nodesMap.get(id) || null;
    }
    
    /**
     * 根据名称查找节点（返回第一个匹配的）
     */
    findNodeByName(name) {
        for (const node of this.nodesMap.values()) {
            if (node.name === name) return node;
        }
        return null;
    }
    
    /**
     * 根据类型查找所有节点
     */
    findNodesByType(type) {
        const nodes = [];
        for (const node of this.nodesMap.values()) {
            if (node.type === type) nodes.push(node);
        }
        return nodes;
    }
    
    /**
     * 根据 Object3D 查找节点
     */
    findNodeByObject3D(object3D) {
        for (const node of this.nodesMap.values()) {
            if (node.object3D === object3D) return node;
        }
        return null;
    }
    
    /**
     * 选中节点
     */
    selectNode(nodeId) {
        const node = this.nodesMap.get(nodeId);
        if (!node) {
            console.warn(`⚠️ 节点不存在: ${nodeId}`);
            return false;
        }
        
        const previousNode = this.selectedNode;
        this.selectedNode = node;
        
        this.emit('nodeSelected', { node, previousNode });
        return true;
    }
    
    /**
     * 取消选中节点（统一的取消选择接口）
     * 
     * ⚠️ 重要：这是取消选择节点的唯一正确方式
     * 
     * 执行流程：
     * 1. 保存之前选中的节点引用
     * 2. 清空 selectedNode 缓存（设置为 null）
     * 3. 触发 nodeDeselected 事件
     * 4. SceneTreeUI.clearSelection() 会响应该事件，执行所有清理逻辑：
     *    - 移除场景树UI的节点高亮
     *    - 移除模型的边缘轮廓线
     *    - 关闭TransformControls（坐标轴）
     *    - 清除网格线
     *    - 关闭属性面板
     * 
     * ⚠️ 注意：永远不要直接设置 this.selectedNode = null，
     *          必须调用此方法以确保所有清理逻辑正确执行
     */
    deselectNode() {
        const previousNode = this.selectedNode;
        this.selectedNode = null; // 清空缓存的选中节点数据
        this.emit('nodeDeselected', { previousNode }); // 触发事件，执行统一的清理逻辑
    }
    
    /**
     * 更新节点数据
     * @param {string} nodeId - 节点ID
     * @param {Object} newNodeData - 新的节点数据（会深度合并）
     */
    updateNode(nodeId, newNodeData) {
        const node = this.nodesMap.get(nodeId);
        if (node) {
            // 深度合并新数据，确保不丢失其他属性
            Object.assign(node, newNodeData);
            // 触发事件通知UI更新
            this.emit('nodeUpdated', { node });
            // console.log(`🔄 节点数据已更新: ${node.name}`); // 静默更新，避免日志过多
        } else {
            console.warn(`⚠️ 尝试更新不存在的节点: ${nodeId}`);
        }
    }
    
    /**
     * 获取所有节点（扁平化）
     */
    getAllNodes() {
        return Array.from(this.nodesMap.values());
    }
    
    /**
     * 获取节点总数
     */
    getNodeCount() {
        return this.nodesMap.size;
    }
    
    /**
     * 遍历所有节点
     */
    traverse(callback) {
        this.root.traverse(callback);
    }
    
    /**
     * 导出树结构为JSON
     */
    toJSON() {
        return {
            root: this.root.toJSON(),
            nodeCount: this.getNodeCount(),
            exportedAt: new Date().toISOString()
        };
    }
    
    /**
     * 从JSON加载树结构
     * @param {Object} json - 场景树JSON数据
     * @param {THREE.Scene} scene - Three.js场景对象
     * @param {Function} onProgress - 进度回调函数(currentIndex, total, nodeName)
     */
    async fromJSON(json, scene, onProgress = null) {
        // 辅助函数：在解析步骤之间添加小延迟，让UI有时间更新
        const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
        
        // 清空当前树
        this.clear();
        
        // 🎯 报告进度：开始解析（使用特殊类型 'parse-step'）
        if (onProgress) {
            onProgress(0, 4, '清空当前场景树...', 'parse-step');
            await delay(50); // 短暂延迟让进度条更新
        }
        
        // 🎯 第一阶段：收集所有模型ID并预加载
        const collectModelIds = (nodeData) => {
            const models = [];
            
            // 检查当前节点是否有模型组件
            if (nodeData.components && nodeData.components.length > 0) {
                const modelComponent = nodeData.components.find(c => c.type === 'model');
                if (modelComponent && modelComponent.modelId) {
                    models.push({
                        id: modelComponent.modelId,
                        type: modelComponent.modelType || 'model', // 🎯 收集模型类型
                        name: nodeData.name // 🎯 收集节点名称作为模型名称提示
                    });
                }
            }
            
            // 递归收集子节点的模型
            if (nodeData.children) {
                nodeData.children.forEach(child => {
                    models.push(...collectModelIds(child));
                });
            }
            
            return models;
        };
        
        // 🎯 报告进度：收集模型ID
        if (onProgress) {
            onProgress(1, 4, '收集场景中的模型信息...', 'parse-step');
            await delay(50);
        }
        
        const allModels = json.root && json.root.children 
            ? json.root.children.reduce((models, child) => [...models, ...collectModelIds(child)], []) 
            : [];
        
        // 🎯 报告进度：去重模型ID
        if (onProgress) {
            onProgress(2, 4, `分析模型依赖 (共 ${allModels.length} 个引用)...`, 'parse-step');
            await delay(50);
        }
        
        // 去重（按 modelId 去重，同时保留 type 和 name 信息）
        const uniqueModelsMap = new Map();
        allModels.forEach(m => {
            if (!uniqueModelsMap.has(m.id)) {
                uniqueModelsMap.set(m.id, m);
            }
        });
        const uniqueModels = Array.from(uniqueModelsMap.values());
        
        // 🎯 报告进度：计算节点总数
        if (onProgress) {
            onProgress(3, 4, `准备加载 ${uniqueModels.length} 个模型...`, 'parse-step');
            await delay(50);
        }
        
        // 🎯 预加载所有模型到缓存（顺序加载，每个模型加载完成后报告进度）
        if (uniqueModels.length > 0 && window.modelLoader) {
            console.log(`📦 开始预加载 ${uniqueModels.length} 个模型...`);
            
            for (let index = 0; index < uniqueModels.length; index++) {
                const model = uniqueModels[index];
                const modelDisplayName = model.name || model.id; // 使用节点名称或ID
                
                try {
                    console.log(`   🔄 [${index + 1}/${uniqueModels.length}] 正在加载模型: ${model.id} (${modelDisplayName})`);
                    
                    // 🎯 传递下载进度回调
                    await window.modelLoader.loadModelById(model.id, true, model.type, (xhr) => {
                        if (onProgress && xhr.lengthComputable) {
                            const downloadProgress = (xhr.loaded / xhr.total);
                            const currentModelProgress = index + downloadProgress;
                            
                            // 计算文件大小（格式化为 KB/MB）
                            const formatBytes = (bytes) => {
                                if (bytes < 1024) return bytes + ' B';
                                if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
                                return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
                            };
                            
                            // 报告下载进度（使用小数表示当前进度）
                            onProgress(
                                currentModelProgress, 
                                uniqueModels.length, 
                                `下载模型: ${modelDisplayName} (${formatBytes(xhr.loaded)}/${formatBytes(xhr.total)})`,
                                'model-download'
                            );
                        }
                    });
                    
                    console.log(`   ✅ [${index + 1}/${uniqueModels.length}] 模型加载完成: ${model.id}`);
                    
                    // 报告预加载完成进度
                    if (onProgress) {
                        onProgress(index + 1, uniqueModels.length, `加载模型完成: ${modelDisplayName}`, 'model-preload');
                    }
                } catch (error) {
                    console.error(`   ❌ [${index + 1}/${uniqueModels.length}] 预加载失败: ${model.id}`, error);
                    // 即使加载失败，也要报告进度，这样进度条会继续前进
                    if (onProgress) {
                        onProgress(index + 1, uniqueModels.length, `加载模型失败: ${modelDisplayName}`, 'model-preload');
                    }
                }
            }
            
            console.log(`✅ 所有模型预加载完成`);
        }
        
        // 第二阶段：构建场景树
        // 计算总节点数
        const countNodes = (nodeData) => {
            let count = 1;
            if (nodeData.children) {
                nodeData.children.forEach(child => {
                    count += countNodes(child);
                });
            }
            return count;
        };
        
        const totalNodes = json.root && json.root.children 
            ? json.root.children.reduce((sum, child) => sum + countNodes(child), 0) 
            : 0;
        
        let loadedCount = 0;
        // ⚡ 全局处理计数器，用于控制延迟频率
        let processedNodesCount = 0;
        
        // 重建树结构
        const buildTree = async (nodeData, parent) => {
            // ⚡ 每处理5个节点强制暂停1ms，让出主线程给UI渲染
            processedNodesCount++;
            if (processedNodesCount % 5 === 0) {
                await delay(1);
            }

            // ✨ 特殊处理环境节点：使用已存在的environmentNode，更新其属性
            if (nodeData.id === 'environment' || nodeData.type === 'environment') {
                // 更新环境节点的 components 数据（如果有）
                if (nodeData.components) {
                    this.environmentNode.components = nodeData.components;
                    
                    // 应用 transform 数据到 object3D
                    const transformComponent = nodeData.components.find(c => c.type === 'transform');
                    if (transformComponent && this.environmentNode.object3D) {
                        const obj = this.environmentNode.object3D;
                        if (transformComponent.position) {
                            obj.position.set(
                                transformComponent.position.x || 0,
                                transformComponent.position.y || 0,
                                transformComponent.position.z || 0
                            );
                        }
                        if (transformComponent.rotation) {
                            obj.rotation.set(
                                transformComponent.rotation.x || 0,
                                transformComponent.rotation.y || 0,
                                transformComponent.rotation.z || 0
                            );
                        }
                        if (transformComponent.scale) {
                            obj.scale.set(
                                transformComponent.scale.x || 1,
                                transformComponent.scale.y || 1,
                                transformComponent.scale.z || 1
                            );
                        }
                    }
                }
                
                // 递归加载环境节点的子节点
                if (nodeData.children) {
                    for (const childData of nodeData.children) {
                        await buildTree(childData, this.environmentNode);
                    }
                }
                return; // 跳过环境节点本身的创建
            }
            
            // ✅ 兼容旧格式（transform 在顶层）和新格式（transform 在 components 中）
            let components = nodeData.components || [];
            
            // 如果旧格式中有 transform，且 components 中没有 transform 组件，迁移到 components
            if (nodeData.transform && !components.find(c => c.type === 'transform')) {
                components = [...components, {
                    type: 'transform',
                    position: nodeData.transform.position || { x: 0, y: 0, z: 0 },
                    rotation: nodeData.transform.rotation || { x: 0, y: 0, z: 0 },
                    scale: nodeData.transform.scale || { x: 1, y: 1, z: 1 }
                }];
            }
            
            // 创建节点配置
            const nodeConfig = {
                id: nodeData.id, // ✅ 使用保存的ID（就是 Object3D 的 uuid）
                name: nodeData.name,
                type: nodeData.type,
                visible: nodeData.visible,
                locked: nodeData.locked,
                userData: nodeData.userData,
                components: components // ✅ 加载组件数据（包含 transform、model 等）
            };
            
            // 如果是空节点或分组节点，需要创建对应的Three.js Group对象
            if (nodeData.type === 'group' || nodeData.type === 'empty') {
                const group = new THREE.Group();
                group.name = nodeData.name;
                group.uuid = nodeData.id; // ✅ 设置 Group 的 uuid 为保存的 id
                nodeConfig.object3D = group;
                // 不在这里添加到场景，让 addChild 方法处理
            }
            
            // 如果是摄像机节点
            if (nodeData.type === 'camera') {
                // 从组件中获取相机参数
                const cameraComponent = nodeConfig.components.find(c => c.type === 'camera');
                const fov = cameraComponent?.fov || 50;
                const near = cameraComponent?.near || 0.3;
                const far = cameraComponent?.far || 1000;
                
                const camera = new THREE.PerspectiveCamera(fov, window.innerWidth / window.innerHeight, near, far);
                camera.name = nodeData.name;
                camera.uuid = nodeData.id;
                
                nodeConfig.object3D = camera;
                
                // 添加相机辅助对象
                const helper = new THREE.CameraHelper(camera);
                helper.name = nodeData.name + '_Helper';
                // 将 helper 存储在 userData 中，选中时显示
                camera.userData.helper = helper;
                // 默认隐藏
                helper.visible = false;
                
                // 🎥 添加相机简模（可视化Mesh）
                const cameraGroup = new THREE.Group();
                cameraGroup.name = 'CameraModel';
                
                // 相机机身
                const bodyGeometry = new THREE.BoxGeometry(0.4, 0.3, 0.2);
                const bodyMaterial = new THREE.MeshBasicMaterial({ color: 0x333333 });
                const bodyMesh = new THREE.Mesh(bodyGeometry, bodyMaterial);
                
                // 相机镜头
                const lensGeometry = new THREE.CylinderGeometry(0.1, 0.1, 0.2, 16);
                lensGeometry.rotateX(-Math.PI / 2); // 旋转使镜头朝向 -Z
                const lensMaterial = new THREE.MeshBasicMaterial({ color: 0x111111 });
                const lensMesh = new THREE.Mesh(lensGeometry, lensMaterial);
                lensMesh.position.z = -0.15;
                
                cameraGroup.add(bodyMesh);
                cameraGroup.add(lensMesh);
                
                // 将简模作为相机的子对象
                camera.add(cameraGroup);
                
                // 将 helper 添加到场景根节点（通过 scene 引用）
                if (scene) {
                    scene.add(helper);
                }
            }
            
            // ✅ 如果节点有模型组件，根据modelId加载3D模型
            if (nodeData.components && nodeData.components.length > 0) {
                const modelComponent = nodeData.components.find(c => c.type === 'model');
                
                // 🎯 处理节点组的子节点：从父节点的 object3D 中查找对应的子对象
                if (modelComponent && modelComponent.fromHierarchy && !modelComponent.modelId) {
                    // 从父节点的 object3D 中查找匹配名称的子对象
                    if (parent && parent.object3D) {
                        let foundObject = null;
                        
                        // 递归查找名称匹配的对象
                        parent.object3D.traverse((child) => {
                            if (child.name === nodeData.name && !foundObject) {
                                foundObject = child;
                            }
                        });
                        
                        if (foundObject) {
                            foundObject.uuid = nodeData.id; // 设置 uuid 为保存的 id
                            nodeConfig.object3D = foundObject;
                        } else {
                            console.warn(`⚠️ 未找到节点组子对象: ${nodeData.name}`);
                        }
                    } else {
                        console.warn(`⚠️ 父节点没有 object3D，无法查找子对象: ${nodeData.name}`);
                    }
                } else if (modelComponent && modelComponent.modelId) {
                    // 🎯 普通节点或根节点：根据 modelId 加载模型
                    // 调用模型加载器加载模型
                    try {
                        const modelLoader = window.modelLoader;
                        if (modelLoader && typeof modelLoader.loadModelById === 'function') {
                            // 🎯 从组件中读取 modelType，默认为 'model'
                            const modelType = modelComponent.modelType || 'model';
                            const object3D = await modelLoader.loadModelById(modelComponent.modelId, true, modelType);
                            if (object3D) {
                                object3D.name = nodeData.name;
                                object3D.uuid = nodeData.id; // ✅ 设置 Object3D 的 uuid 为保存的 id
                                nodeConfig.object3D = object3D;
                                
                                // ✅ 恢复保存的 importScale（如果存在）
                                // 注意：loadModelById 已经设置了默认的 importScale，但如果 JSON 中有保存的值，应该使用保存的值
                                if (nodeData.importScale !== undefined && nodeData.importScale !== null) {
                                    object3D.userData.importScale = nodeData.importScale;
                                }
                                
                                // ✅ 保存模型的原始缩放（从加载的object3D读取）
                                if (!nodeConfig.originalScale) {
                                    nodeConfig.originalScale = {
                                        x: object3D.scale.x,
                                        y: object3D.scale.y,
                                        z: object3D.scale.z
                                    };
                                }
                                
                                // ✅ 修正可能错误的缩放值
                                const transformComponent = nodeConfig.components.find(c => c.type === 'transform');
                                if (transformComponent && transformComponent.scale) {
                                    // 检测是否是疑似错误的缩放值（大于10或小于0.001）
                                    const savedScale = transformComponent.scale;
                                    const isSuspicious = savedScale.x > 10 || savedScale.y > 10 || savedScale.z > 10 ||
                                                        savedScale.x < 0.001 || savedScale.y < 0.001 || savedScale.z < 0.001;
                                    
                                    if (isSuspicious) {
                                        console.warn(`⚠️ 检测到疑似错误的缩放值: (${savedScale.x}, ${savedScale.y}, ${savedScale.z})`);
                                        // 重置为默认值1
                                        transformComponent.scale = { x: 1, y: 1, z: 1 };
                                    }
                                }
                            } else {
                                console.warn(`⚠️ 模型加载返回空对象: ${modelComponent.modelId}`);
                            }
                        } else {
                            console.warn(`⚠️ modelLoader.loadModelById 不可用`);
                        }
                    } catch (error) {
                        console.error(`❌ 加载模型失败: ${modelComponent.modelId}`, error);
                    }
                }
            }
            
            const node = new TreeNode(nodeConfig);
            
            // ✅ 不需要加载 baseScale，运行时通过 getBaseScale() 动态获取
            
            // 应用transform到object3D
            if (nodeData.transform && node.object3D) {
                node.applyTransformToObject3D();
            }
            
            // 💾 保存模型内部所有层级的原始transform（在应用节点transform之后）
            if (node.object3D && node.modelId) {
                node.saveModelHierarchyTransforms();
            }
            
            parent.addChild(node);
            this.nodesMap.set(node.id, node);
             // 如果节点有模型组件且有材质绑定数据，立即应用材质
             if (nodeData.components && nodeData.components.length > 0) {
                 const modelComponent = nodeData.components.find(c => c.type === 'model');
                 if (modelComponent && modelComponent.meshMaterials && Object.keys(modelComponent.meshMaterials).length > 0) {
                     // 获取项目ID并应用材质
                     const projectId = window.projectManager?.getCurrentProject()?.id;
                     if (projectId) {
                         // ⚡ 场景加载时传入 isLoadingScene=true，不写入材质引用
                         await this.applyMeshMaterials(node, modelComponent, projectId, true);
                     }
                 }
             }
            
            // 更新进度
            loadedCount++;
            if (onProgress) {
                onProgress(loadedCount, totalNodes, nodeData.name, nodeData.type);
            }
            
            // 递归构建子节点
            if (nodeData.children) {
                for (const childData of nodeData.children) {
                    await buildTree(childData, node);
                }
            }
        };
        
        if (json.root && json.root.children) {
            for (const childData of json.root.children) {
                await buildTree(childData, this.root);
            }
        }
    }
    
    /**
     * 清空所有节点（保留根节点和环境节点）
     */
    async clear() {
        const children = [...this.root.children];
        for (const child of children) {
            // ✨ 跳过环境节点
            if (child.id !== 'environment') {
                await this.removeNode(child.id);
            }
        }
        this.deselectNode(); // 使用统一的取消选择接口
    }
    
    /**
     * 事件系统 - 注册事件
     */
    on(event, callback) {
        if (!this.eventCallbacks[event]) {
            this.eventCallbacks[event] = [];
        }
        this.eventCallbacks[event].push(callback);
    }
    
    /**
     * 事件系统 - 触发事件
     */
    emit(event, data) {
        if (this.eventCallbacks[event]) {
            this.eventCallbacks[event].forEach(callback => {
                try {
                    callback(data);
                } catch (error) {
                    console.error(`❌ 事件回调错误 [${event}]:`, error);
                }
            });
        }
    }
    
    /**
     * 打印树结构（调试用）
     */
    printTree(node = this.root, indent = '') {
        node.children.forEach((child, index) => {
            const isLast = index === node.children.length - 1;
            this.printTree(child, indent + (isLast ? '   ' : '│  '));
        });
    }
    
    /**
     * 获取树结构的文本表示
     */
    getTreeString(node = this.root, indent = '', isLast = true) {
        const prefix = isLast ? '└── ' : '├── ';
        const childIndent = indent + (isLast ? '    ' : '│   ');
        
        let result = indent + prefix + `${node.name} (${node.type})\n`;
        
        node.children.forEach((child, index) => {
            const childIsLast = index === node.children.length - 1;
            result += this.getTreeString(child, childIndent, childIsLast);
        });
        
        return result;
    }
    
    /**
     * 从材质数据创建Three.js材质对象
     * @param {Object} materialData - 材质数据
     * @returns {THREE.Material} Three.js材质对象
     */
    async createThreeMaterialFromData(materialData) {
        const MaterialClass = THREE[materialData.type] || THREE.MeshStandardMaterial;
        
        const params = {
            name: materialData.name || 'Material',
            color: new THREE.Color(materialData.color || '#ffffff'),
            opacity: materialData.opacity !== undefined ? materialData.opacity : 1.0,
            // 🔧 修复：透明相关参数 - 关键修复！
            transparent: materialData.transparent !== undefined ? materialData.transparent : false,
            alphaTest: materialData.alphaTest !== undefined ? materialData.alphaTest : 0,
            depthWrite: materialData.depthWrite !== undefined ? materialData.depthWrite : true,
            depthTest: materialData.depthTest !== undefined ? materialData.depthTest : true,
            side: materialData.doubleSided ? THREE.DoubleSide : THREE.FrontSide
        };
        
        // 根据材质类型添加特定参数
        if (materialData.type === 'MeshStandardMaterial' || materialData.type === 'MeshPhysicalMaterial') {
            params.metalness = materialData.metalness !== undefined ? materialData.metalness : 0.5;
            params.roughness = materialData.roughness !== undefined ? materialData.roughness : 0.5;
            params.emissive = new THREE.Color(materialData.emissive || '#000000');
            params.emissiveIntensity = materialData.emissiveIntensity !== undefined ? materialData.emissiveIntensity : 0;
        } else if (materialData.type === 'MeshPhongMaterial') {
            params.shininess = materialData.shininess !== undefined ? materialData.shininess : 30;
            params.emissive = new THREE.Color(materialData.emissive || '#000000');
            params.specular = new THREE.Color(materialData.specular || '#111111');
        } else if (materialData.type === 'MeshLambertMaterial') {
            params.emissive = new THREE.Color(materialData.emissive || '#000000');
        }
        
        const material = new MaterialClass(params);
        
        // 🔍 调试日志：检查透明参数是否正确应用
        if (materialData.transparent || materialData.alphaTest > 0 || materialData.opacity < 1) {
            console.log(`🎭 [材质创建] 透明材质: ${materialData.displayName || materialData.name}`, {
                输入参数: {
                    transparent: materialData.transparent,
                    alphaTest: materialData.alphaTest,
                    depthWrite: materialData.depthWrite,
                    opacity: materialData.opacity
                },
                Three材质属性: {
                    transparent: material.transparent,
                    alphaTest: material.alphaTest,
                    depthWrite: material.depthWrite,
                    opacity: material.opacity
                }
            });
        }
        
        // ⭐ 应用额外的材质属性
        if (materialData.aoIntensity !== undefined && material.aoMapIntensity !== undefined) {
            material.aoMapIntensity = materialData.aoIntensity;
        }
        if (materialData.bumpScale !== undefined && material.bumpScale !== undefined) {
            material.bumpScale = materialData.bumpScale;
        }
        
        // ⭐ 加载纹理贴图（异步）
        await this.loadTexturesForMaterial(material, materialData);
        
        return material;
    }
    
    /**
     * 为材质加载纹理（SceneTreeManager版本）
     * 优先使用预加载的纹理缓存，如果缓存中没有则动态加载
     * @param {THREE.Material} material - 材质对象
     * @param {Object} materialData - 材质数据
     */
    async loadTexturesForMaterial(material, materialData) {
        const textureLoader = new THREE.TextureLoader();
        const backendUrl = window.APP_CONFIG?.backendUrl || window.location.origin;
        const projectId = window.projectManager?.getCurrentProject()?.id;
        
        if (!projectId) {
            console.warn('⚠️ [SceneTree纹理] 无法获取项目ID');
            return;
        }
        
        // 获取资源预加载器
        const resourcePreloader = window.resourcePreloader;
        
        // 辅助函数：获取纹理（优先从缓存）
        const getTexture = async (textureNameOrId, isSRGB = false, needsUVTransform = false) => {
            if (!textureNameOrId) return null;
            
            // 1. 尝试从预加载缓存获取
            if (resourcePreloader) {
                const cachedTexture = resourcePreloader.getCachedTexture(projectId, textureNameOrId);
                if (cachedTexture) {
                    // ✅ 修复：总是克隆纹理，避免共享导致的UV参数冲突
                    // 虽然会稍微影响性能，但可以确保每个材质的UV参数独立
                    const clonedTexture = cachedTexture.clone();
                    if (isSRGB) {
                        clonedTexture.colorSpace = THREE.SRGBColorSpace;
                    }
                    // ✅ 重置UV参数为默认值，避免继承缓存纹理的旧参数
                    clonedTexture.repeat.set(1, 1);
                    clonedTexture.offset.set(0, 0);
                    clonedTexture.rotation = 0;
                    clonedTexture.center.set(0.5, 0.5);
                    clonedTexture.wrapS = THREE.RepeatWrapping;
                    clonedTexture.wrapT = THREE.RepeatWrapping;
                    
                    // 🔧 保留高质量纹理过滤设置
                    clonedTexture.minFilter = cachedTexture.minFilter;
                    clonedTexture.magFilter = cachedTexture.magFilter;
                    clonedTexture.anisotropy = cachedTexture.anisotropy;
                    
                    clonedTexture.needsUpdate = true;
                    return clonedTexture;
                }
            }
            
            // 2. 如果缓存中没有，动态加载（降级方案）
            // 查找纹理路径
            const texturePath = await this.findTexturePath(projectId, textureNameOrId);
            if (!texturePath) return null;
            
            // 动态加载纹理
            return new Promise((resolve) => {
                textureLoader.load(
                    `${backendUrl}${texturePath}`,
                    (texture) => {
                        if (isSRGB) {
                            texture.colorSpace = THREE.SRGBColorSpace;
                        }
                        
                        // 🔧 修复模糊问题：设置高质量纹理过滤
                        texture.generateMipmaps = true;
                        texture.minFilter = THREE.LinearMipmapLinearFilter;
                        texture.magFilter = THREE.LinearFilter;
                        const renderer = window.manager?.renderer;
                        const maxAnisotropy = renderer ? renderer.capabilities.getMaxAnisotropy() : 16;
                        texture.anisotropy = maxAnisotropy;
                        texture.needsUpdate = true;
                        
                        resolve(texture);
                    },
                    undefined,
                    (error) => {
                        console.warn(`❌ [SceneTree纹理] 动态加载失败: ${textureNameOrId}`, error);
                        resolve(null);
                    }
                );
            });
        };
        
        // 辅助函数：查找纹理路径（仅在缓存未命中时使用）
        this.findTexturePath = async (projectId, textureNameOrPath) => {
            if (!textureNameOrPath) return null;
            
            // 如果已经是路径，直接返回
            if (textureNameOrPath.startsWith('/')) {
                return textureNameOrPath;
            }
            
            // 通过API查找纹理
            try {
                const response = await fetch(`/api/projects/${projectId}/textures`);
                if (!response.ok) return null;
                
                const result = await response.json();
                if (!result.success || !result.data) return null;
                
                const texture = result.data.find(t => 
                    t.displayName === textureNameOrPath || 
                    t.name === textureNameOrPath ||
                    t.id === textureNameOrPath
                );
                
                if (texture && texture.id) {
                    return `/api/projects/${projectId}/textures/${texture.id}/file`;
                }
                
                return null;
            } catch (error) {
                console.error('❌ [SceneTree纹理] 查找纹理失败:', error);
                return null;
            }
        };
        
        // 检查是否需要自定义UV变换
        const hasCustomUVTransform = () => {
            if (!materialData) return false;
            
            const uvRepeatX = materialData.uvRepeatX !== undefined ? materialData.uvRepeatX : 1;
            const uvRepeatY = materialData.uvRepeatY !== undefined ? materialData.uvRepeatY : 1;
            const uvOffsetX = materialData.uvOffsetX !== undefined ? materialData.uvOffsetX : 0;
            const uvOffsetY = materialData.uvOffsetY !== undefined ? materialData.uvOffsetY : 0;
            const uvRotation = materialData.uvRotation !== undefined ? materialData.uvRotation : 0;
            const uvCenterX = materialData.uvCenterX !== undefined ? materialData.uvCenterX : 0.5;
            const uvCenterY = materialData.uvCenterY !== undefined ? materialData.uvCenterY : 0.5;
            
            // 检查是否使用非默认值
            return uvRepeatX !== 1 || uvRepeatY !== 1 || 
                   uvOffsetX !== 0 || uvOffsetY !== 0 || 
                   uvRotation !== 0 || 
                   uvCenterX !== 0.5 || uvCenterY !== 0.5;
        };
        
        // 应用UV变换（仅在需要时调用）
        const applyUVTransform = (texture) => {
            if (!texture || !materialData) return;
            
            const uvRepeatX = materialData.uvRepeatX !== undefined ? materialData.uvRepeatX : 1;
            const uvRepeatY = materialData.uvRepeatY !== undefined ? materialData.uvRepeatY : 1;
            const uvOffsetX = materialData.uvOffsetX !== undefined ? materialData.uvOffsetX : 0;
            const uvOffsetY = materialData.uvOffsetY !== undefined ? materialData.uvOffsetY : 0;
            const uvRotation = materialData.uvRotation !== undefined ? materialData.uvRotation : 0;
            const uvCenterX = materialData.uvCenterX !== undefined ? materialData.uvCenterX : 0.5;
            const uvCenterY = materialData.uvCenterY !== undefined ? materialData.uvCenterY : 0.5;
            
            texture.repeat.set(uvRepeatX, uvRepeatY);
            texture.offset.set(uvOffsetX, uvOffsetY);
            texture.rotation = uvRotation;
            texture.center.set(uvCenterX, uvCenterY);
            texture.wrapS = THREE.RepeatWrapping;
            texture.wrapT = THREE.RepeatWrapping;
            texture.needsUpdate = true;
        };
        
        // === 使用预加载纹理或动态加载 ===
        
        // ⚡ 检查是否需要自定义UV变换（只检查一次，所有贴图共享同样的UV设置）
        const needsUVTransform = hasCustomUVTransform();
        
        // 基础颜色贴图 (SRGB色彩空间)
        if (materialData.map) {
            const texture = await getTexture(materialData.map, true, needsUVTransform);
            if (texture) {
                // ✅ 总是应用UV变换，确保参数正确
                applyUVTransform(texture);
                material.map = texture;
                
                // 🔧 修复：PNG透明贴图支持 - 智能透明检测
                const mapName = String(materialData.map).toLowerCase();
                // 检查是否为透明格式：文件名后缀 或 纹理本身包含Alpha通道
                const isTransparentFormat = mapName.match(/\.(png|tga|webp)$/) || texture.format === THREE.RGBAFormat;
                
                // 检查是否为马路线材质（名称包含关键词）
                const matName = (materialData.displayName || materialData.name || '').toLowerCase();
                const isRoadLine = mapName.includes('road') || mapName.includes('line') || mapName.includes('马路') || mapName.includes('线') ||
                                 matName.includes('road') || matName.includes('line') || matName.includes('马路') || matName.includes('线');

                if (isTransparentFormat || isRoadLine) {
                    if (isRoadLine) {
                        // 🛣️ 马路线专用策略：必须使用alphaTest，且开启深度写入
                        // 这样可以去除黑色背景，同时保持正确的深度遮挡关系
                        material.alphaTest = 0.1; // 低阈值，保留更多细节
                        material.transparent = false; // 关闭混合，避免排序问题
                        material.depthWrite = true; // 开启深度写入
                        material.side = THREE.DoubleSide; // 双面渲染
                        console.log(`   🛣️ 检测到马路线贴图，启用alphaTest模式 (threshold=0.1)`);
                    } else {
                        // 🌿 普通透明物体：使用transparent + alphaTest组合
                        material.alphaTest = 0.5;
                        material.transparent = true;
                        material.depthWrite = false;
                        console.log(`   ✓ 检测到透明通道贴图，已启用transparent + alphaTest组合模式`);
                    }
                    
                    material.depthTest = true;
                    // 🔑 设置渲染顺序，确保透明物体最后渲染
                    material.userData.needsRenderOrder = true;
                }
                
                material.needsUpdate = true;
            }
        }
        
        // 法线贴图
        if (materialData.normalMap) {
            const texture = await getTexture(materialData.normalMap, false, needsUVTransform);
            if (texture) {
                // ✅ 总是应用UV变换，确保参数正确
                applyUVTransform(texture);
                material.normalMap = texture;
                material.needsUpdate = true;
            }
        }
        
        // 凹凸贴图
        if (materialData.bumpMap) {
            const texture = await getTexture(materialData.bumpMap, false, needsUVTransform);
            if (texture) {
                // ✅ 总是应用UV变换，确保参数正确
                applyUVTransform(texture);
                material.bumpMap = texture;
                material.needsUpdate = true;
            }
        }
        
        // AO贴图
        if (materialData.aoMap) {
            const texture = await getTexture(materialData.aoMap, false, needsUVTransform);
            if (texture) {
                // ✅ 总是应用UV变换，确保参数正确
                applyUVTransform(texture);
                material.aoMap = texture;
                material.needsUpdate = true;
            }
        }
        
        // 金属度贴图
        if (materialData.metalnessMap && material.metalnessMap !== undefined) {
            const texture = await getTexture(materialData.metalnessMap, false, needsUVTransform);
            if (texture) {
                // ✅ 总是应用UV变换，确保参数正确
                applyUVTransform(texture);
                material.metalnessMap = texture;
                material.needsUpdate = true;
            }
        }
        
        // 粗糙度贴图
        if (materialData.roughnessMap && material.roughnessMap !== undefined) {
            const texture = await getTexture(materialData.roughnessMap, false, needsUVTransform);
            if (texture) {
                // ✅ 总是应用UV变换，确保参数正确
                applyUVTransform(texture);
                material.roughnessMap = texture;
                material.needsUpdate = true;
            }
        }
        
        // 自发光贴图 (SRGB色彩空间)
        if (materialData.emissiveMap && material.emissiveMap !== undefined) {
            const texture = await getTexture(materialData.emissiveMap, true, needsUVTransform);
            if (texture) {
                // ✅ 总是应用UV变换，确保参数正确
                applyUVTransform(texture);
                material.emissiveMap = texture;
                material.needsUpdate = true;
            }
        }
        
        // 透明度贴图
        if (materialData.alphaMap) {
            const texture = await getTexture(materialData.alphaMap, false, needsUVTransform);
            if (texture) {
                // ✅ 总是应用UV变换，确保参数正确
                applyUVTransform(texture);
                material.alphaMap = texture;
                
                // 🔧 修复：alphaMap使用transparent + alphaTest组合
                material.alphaTest = 0.5;
                material.transparent = true;
                material.depthWrite = false;
                material.depthTest = true;
                // 🔑 设置渲染顺序，确保透明物体最后渲染
                material.userData.needsRenderOrder = true;
                console.log(`   ✓ 检测到alphaMap，已启用transparent + alphaTest组合模式`);
                
                material.needsUpdate = true;
            }
        }
        
        // 置换贴图
        if (materialData.displacementMap) {
            const texture = await getTexture(materialData.displacementMap, false, needsUVTransform);
            if (texture) {
                // ✅ 总是应用UV变换，确保参数正确
                applyUVTransform(texture);
                material.displacementMap = texture;
                material.needsUpdate = true;
            }
        }
        
        // 🎨 贴图加载完成后，检查并修复暗色透明材质
        this.checkAndFixDarkTransparentMaterial(material, materialData);
        
        // 所有纹理加载完成后统一渲染
        if (window.manager && window.manager.render) {
            window.manager.render();
        }
    }
    
    /**
     * 检查并修复单个暗色透明材质（在贴图加载完成后调用）
     * @param {THREE.Material} material - 材质对象
     * @param {Object} materialData - 材质数据
     */
    checkAndFixDarkTransparentMaterial(material, materialData) {
        const matName = (materialData.displayName || materialData.name || '').toLowerCase();
        const isRoadLine = matName.includes('马路') || matName.includes('线') || 
                         matName.includes('road') || matName.includes('line');
        
        // 🎯 通用规则：检查透明材质的透明处理方式
        const isTransparent = material.transparent || material.alphaTest > 0 || material.opacity < 1;
        
        if (isTransparent && material.map) {
            console.log(`🎨 [源头修复] 检测到有贴图的透明材质: ${materialData.displayName || materialData.name}`);
            console.log(`   贴图URL: ${material.map.image?.src || '未知'}`);
            console.log(`   当前基础颜色: RGB(${material.color.r.toFixed(3)}, ${material.color.g.toFixed(3)}, ${material.color.b.toFixed(3)})`);
            console.log(`   透明设置: transparent=${material.transparent}, alphaTest=${material.alphaTest}, opacity=${material.opacity}`);
            
            // 🎯 关键：确保透明区域正确处理，不透明区域正常计算
            if (isRoadLine) {
                // 马路线使用alphaTest模式，确保透明区域完全透明
                material.transparent = false;
                material.alphaTest = Math.max(0.1, material.alphaTest || 0.1); // 确保有合理的阈值
                material.depthWrite = true;
                material.depthTest = true;
                console.log(`   🛣️ 马路线透明模式: alphaTest=${material.alphaTest}`);
            } else {
                // 其他透明材质，优化透明处理
                if (material.alphaTest > 0) {
                    // 使用alphaTest模式
                    material.transparent = false;
                    if (material.alphaTest > 0.8) material.alphaTest = 0.5; // 限制过高的阈值
                    material.depthWrite = true;
                    console.log(`   🔧 使用alphaTest模式: ${material.alphaTest}`);
                } else {
                    // 使用transparent模式
                    material.transparent = true;
                    material.depthWrite = false;
                    console.log(`   🔧 使用transparent模式`);
                }
            }
            
            // 🎯 检测黑色贴图问题
            if (material.map.image && material.map.image.complete) {
                try {
                    const canvas = document.createElement('canvas');
                    const ctx = canvas.getContext('2d');
                    canvas.width = Math.min(material.map.image.width, 10);
                    canvas.height = Math.min(material.map.image.height, 10);
                    
                    ctx.drawImage(material.map.image, 0, 0, canvas.width, canvas.height);
                    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                    const data = imageData.data;
                    
                    let totalR = 0, totalG = 0, totalB = 0, totalA = 0;
                    let opaquePixels = 0;
                    const pixelCount = data.length / 4;
                    
                    for (let i = 0; i < data.length; i += 4) {
                        const a = data[i + 3];
                        totalA += a;
                        
                        // 只统计不透明像素的颜色
                        if (a > 128) { // 不透明像素
                            totalR += data[i];
                            totalG += data[i + 1];
                            totalB += data[i + 2];
                            opaquePixels++;
                        }
                    }
                    
                    const avgA = totalA / pixelCount;
                    
                    if (opaquePixels > 0) {
                        const avgR = totalR / opaquePixels;
                        const avgG = totalG / opaquePixels;
                        const avgB = totalB / opaquePixels;
                        
                        console.log(`   📊 贴图分析: 不透明区域平均颜色 RGB(${Math.round(avgR)}, ${Math.round(avgG)}, ${Math.round(avgB)})`);
                        console.log(`   📊 透明度分析: 平均Alpha=${Math.round(avgA)}, 不透明像素=${opaquePixels}/${pixelCount}`);
                        
                        if (avgR < 50 && avgG < 50 && avgB < 50) {
                            console.log(`   🚨 检测到黑色不透明区域！`);
                            console.log(`   💡 说明：不透明区域是黑色的，会与基础颜色正常相乘计算`);
                            console.log(`   🔧 建议：调整基础颜色或贴图内容来改善显示效果`);
                        }
                    } else {
                        console.log(`   📊 贴图全透明，平均Alpha=${Math.round(avgA)}`);
                    }
                } catch (error) {
                    console.log(`   贴图分析失败: ${error.message}`);
                }
            }
            
            material.needsUpdate = true;
            console.log(`   ✅ 透明材质优化完成`);
            console.log(`   💡 原理：不透明区域=贴图×基础颜色×参数，透明区域直接透明`);
            
        } else {
            // 🎯 无贴图材质：可以直接调整基础颜色
            const isTransparent = material.transparent || material.alphaTest > 0 || material.opacity < 1;
            
            if (isTransparent) {
                const isDark = material.color.r < 0.6 && material.color.g < 0.6 && material.color.b < 0.6;
                
                if (isDark) {
                    console.log(`🎨 [源头修复] 检测到暗色透明材质（无贴图）: ${materialData.displayName || materialData.name}`);
                    console.log(`   修复前: RGB(${material.color.r.toFixed(3)}, ${material.color.g.toFixed(3)}, ${material.color.b.toFixed(3)})`);
                    
                    if (isRoadLine) {
                        // 无贴图马路线
                        material.color.setRGB(0.8, 0.8, 0.8); // 浅灰色
                        material.transparent = false;
                        material.alphaTest = 0;
                        material.depthWrite = true;
                    } else {
                        // 其他无贴图透明材质
                        const avgColor = (material.color.r + material.color.g + material.color.b) / 3;
                        const compensation = Math.min(2.5, 0.8 / Math.max(avgColor, 0.01));
                        
                        const newR = Math.min(2.0, material.color.r * compensation);
                        const newG = Math.min(2.0, material.color.g * compensation);
                        const newB = Math.min(2.0, material.color.b * compensation);
                        
                        material.color.setRGB(newR, newG, newB);
                    }
                    
                    material.needsUpdate = true;
                    console.log(`   🎨 无贴图透明材质修复: RGB(${material.color.r.toFixed(3)}, ${material.color.g.toFixed(3)}, ${material.color.b.toFixed(3)})`);
                }
            }
        }
    }
    
    /**
     * 自动修复节点中的透明材质 - Alpha优先策略
     * @param {TreeNode} node - 场景树节点
     */
    autoFixDarkTransparentMaterials(node) {
        if (!node.object3D) return;
        
        let fixedCount = 0;
        
        node.object3D.traverse((obj) => {
            if (obj.isMesh && obj.material) {
                const materials = Array.isArray(obj.material) ? obj.material : [obj.material];
                
                materials.forEach((mat) => {
                    // 🎯 Alpha优先策略：检查是否为透明材质
                    const hasAlphaTransparency = mat.transparent || mat.alphaTest > 0 || mat.opacity < 1 || !!mat.alphaMap;
                    
                    if (hasAlphaTransparency) {
                        console.log(`🔧 [Alpha优先修复] 透明材质: ${obj.name} - ${mat.userData?.materialName || mat.name}`);
                        console.log(`   修复前: RGB(${mat.color.r.toFixed(3)}, ${mat.color.g.toFixed(3)}, ${mat.color.b.toFixed(3)}), opacity=${mat.opacity}, alphaTest=${mat.alphaTest}`);
                        
                        // 🔑 关键策略：alpha值为透明时，基础颜色设为白色，让alpha通道主导
                        const hasAlpha = mat.opacity < 1 || mat.alphaTest > 0 || !!mat.alphaMap;
                        
                        if (hasAlpha) {
                            // 有alpha设置时，基础颜色设为白色，不干扰alpha效果
                            mat.color.setRGB(1.0, 1.0, 1.0);
                            // 🔧 关键修复：强制触发材质更新，确保颜色变化立即生效
                            mat.needsUpdate = true;
                            console.log(`   🎨 Alpha优先策略：基础颜色设为白色，强制更新材质`);
                        }
                        
                        // 🎯 根据透明类型设置正确的参数
                        const matName = (mat.userData?.materialName || mat.name || '').toLowerCase();
                        const meshName = (obj.name || '').toLowerCase();
                        const isRoadLine = matName.includes('马路') || matName.includes('线') || 
                                         meshName.includes('马路') || meshName.includes('线') ||
                                         matName.includes('road') || matName.includes('line');
                        
                        if (mat.opacity < 1) {
                            // opacity透明模式：以opacity值为准
                            mat.transparent = true;
                            mat.alphaTest = 0;
                            mat.depthWrite = false;
                            mat.depthTest = true;
                            obj.renderOrder = isRoadLine ? 100 : 999;
                            console.log(`   🔧 opacity透明模式：opacity=${mat.opacity}, renderOrder=${obj.renderOrder}`);
                            
                        } else if (mat.alphaTest > 0 || mat.alphaMap) {
                            // alphaTest透明模式：硬边透明
                            if (isRoadLine) {
                                mat.transparent = false;
                                mat.alphaTest = Math.max(0.1, mat.alphaTest || 0.5);
                                mat.depthWrite = true;
                                mat.depthTest = true;
                                obj.renderOrder = 100;
                                console.log(`   🛣️ 马路线alphaTest模式：alphaTest=${mat.alphaTest}`);
                            } else {
                                mat.transparent = false;
                                mat.alphaTest = mat.alphaTest || 0.5;
                                mat.depthWrite = true;
                                mat.depthTest = true;
                                obj.renderOrder = 200;
                                console.log(`   🔧 alphaTest透明模式：alphaTest=${mat.alphaTest}`);
                            }
                            
                        } else if (mat.transparent) {
                            // 纯transparent模式
                            mat.alphaTest = 0;
                            mat.depthWrite = false;
                            mat.depthTest = true;
                            obj.renderOrder = 999;
                            console.log(`   🔧 transparent模式：基础颜色白色化`);
                        }
                        
                        mat.needsUpdate = true;
                        fixedCount++;
                        
                        console.log(`   ✅ Alpha优先修复完成: RGB(${mat.color.r.toFixed(3)}, ${mat.color.g.toFixed(3)}, ${mat.color.b.toFixed(3)})`);
                        console.log(`   💡 原理：alpha值主导透明效果，基础颜色和贴图RGB影响降低`);
                    }
                });
            }
        });
        
        if (fixedCount > 0) {
            console.log(`🎨 [Alpha优先修复] 节点 "${node.name}" 修复了 ${fixedCount} 个透明材质`);
            
            // 触发渲染更新
            if (window.manager && window.manager.render) {
                window.manager.render();
            }
        }
    }
    
    /**
     * 应用材质到节点的mesh（在模型加载时调用）
     * @param {TreeNode} node - 场景树节点
     * @param {Object} modelComponent - 模型组件数据
     * @param {string} projectId - 项目ID
     * @param {boolean} isLoadingScene - 是否是场景加载（true=只读取，false=需要写入引用）
     */
    async applyMeshMaterials(node, modelComponent, projectId, isLoadingScene = false) {
        try {
            // 检查是否有材质绑定数据
            if (!modelComponent.meshMaterials || Object.keys(modelComponent.meshMaterials).length === 0) {
                return; // 没有材质绑定
            }
            
            // 获取材质库管理器
            const materialLibraryManager = getMaterialLibraryManager(projectId);
            
            // ⚡ 性能优化：先收集所有唯一的materialDisplayName，优先从预加载缓存获取
            const uniqueMaterialNames = new Set();
            for (const materialName of Object.values(modelComponent.meshMaterials)) {
                // ✅ 新架构：值直接是 materialDisplayName（字符串）
                if (materialName && typeof materialName === 'string' && materialName !== "0") {
                    uniqueMaterialNames.add(materialName);
                }
            }
            
            // ⚡ 批量加载材质数据并缓存（优先从预加载缓存获取）
            const materialDataCache = new Map();
            const loadPromises = Array.from(uniqueMaterialNames).map(async (materialDisplayName) => {
                try {
                    // 优先从预加载缓存获取
                    let materialData = window.resourcePreloader?.getCachedMaterialData(materialDisplayName);
                    
                    // 如果缓存中没有，再从API加载
                    if (!materialData) {
                        materialData = await materialLibraryManager.getMaterial(materialDisplayName);
                    }
                    
                    if (materialData) {
                        materialDataCache.set(materialDisplayName, materialData);
                    }
                } catch (error) {
                    console.warn(`   ⚠️ 加载材质失败 (displayName: ${materialDisplayName}):`, error);
                }
            });
            
            await Promise.all(loadPromises);
            
            // 遍历所有mesh材质绑定
            let appliedCount = 0;
            let skippedCount = 0;
            for (const [meshName, materialDisplayName] of Object.entries(modelComponent.meshMaterials)) {
                try {
                    // ⚡ meshName 方案：直接通过 meshName 查找（稳定且高效）
                    const meshObject = node.object3D.getObjectByName(meshName);
                    
                    if (!meshObject || !meshObject.isMesh) {
                        console.warn(`   ⚠️ 未找到Mesh: ${meshName}`);
                        continue;
                    }
                    
                    // 🎯 如果materialDisplayName为"0"或空，跳过（使用自身材质）
                    if (!materialDisplayName || materialDisplayName === "0") {
                        skippedCount++;
                        continue;
                    }
                    
                    // ⚡ 从本地缓存获取材质数据（而不是重复请求API）
                    const materialData = materialDataCache.get(materialDisplayName);
                    if (!materialData) {
                        console.warn(`   ⚠️ 材质不存在 (displayName: ${materialDisplayName})，将使用自身材质`);
                        continue;
                    }
                    
                    // 创建并应用材质（异步）
                    const material = await this.createThreeMaterialFromData(materialData);
                    material.userData.materialId = materialDisplayName; // 使用 displayName 作为 materialId
                    material.userData.materialName = materialData.displayName;
                    
                    meshObject.material = material;
                    meshObject.material.needsUpdate = true;
                    
                    // 如果材质是透明的，设置mesh的renderOrder（用于正确的渲染顺序）
                    if (material.transparent || material.alphaMap || material.alphaTest > 0 || material.userData.needsRenderOrder) {
                        // 🔧 修复：根据物体类型设置分层renderOrder
                        const objName = (meshName || '').toLowerCase();
                        
                        if (objName.includes('road') || objName.includes('line') || objName.includes('马路') || objName.includes('线')) {
                            // 马路线等贴地透明物体
                            meshObject.renderOrder = 100;
                        } else if (meshObject.position.y < 0.1) {
                            // 接近地面的透明物体
                            meshObject.renderOrder = 200;
                        } else {
                            // 其他透明物体
                            meshObject.renderOrder = 999;
                        }
                    }
                    
                    appliedCount++;
                    
                } catch (error) {
                    console.error(`   ❌ 应用材质失败 (mesh: ${meshName}):`, error);
                }
            }
            
            // 🔄 更新材质引用（仅在创建/编辑时，加载场景时跳过）
            if (appliedCount > 0 && !isLoadingScene) {
                const sceneId = window.manager?.getCurrentSceneName();
                
                if (sceneId && projectId) {
                    try {
                        // 直接调用批量更新材质引用
                        await addNodeMaterialReferences(projectId, modelComponent.meshMaterials, sceneId, node.id);
                    } catch (error) {
                        console.error(`❌ 材质引用更新失败 (节点: ${node.name}):`, error);
                    }
                }
            }
            
            // 🎨 自动修复暗色透明材质（在材质绑定完成后）
            if (appliedCount > 0) {
                this.autoFixDarkTransparentMaterials(node);
            }
            
        } catch (error) {
            console.error('❌ [TreeManager] 应用材质失败:', error);
        }
    }
}

/**
 * 导出默认实例创建函数
 */
export function createSceneTreeManager(scene) {
    return new SceneTreeManager(scene);
}


